import { UserEntity } from "../entity/user.entity";
import { DataSource, Repository } from "typeorm";
import { SigningContractEntity } from "../entity/signingContract.entity";
import { InjectRepository } from "@nestjs/typeorm";
import { ContractEntity } from "../entity/contract.entity";
import { HttpException } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { COS } from "../utils/cos";
import * as process from "process";
import { currentTime, generateRandomString, padWithZeros, promiseExec } from "../utils/base";
import { unlinkFile } from "../utils/image_helper";
import { SignPactDto } from "../dto/signPact.dto";
import { convertDocx } from "../utils/docx_template";
import { getCurrentDate } from "../utils/date";
import { SignStudentPactDto } from "../dto/signStudentPact.dto";
import { SignedContractsEntity } from "../entity/signedContracts.entity";
import { PartnersEntity } from "../entity/partners.entity";
import { PactDetailDto } from "../dto/pact.dto";
import { assets_path } from "../main";
import * as fs from "node:fs";

export class PactService {
  constructor(
    @InjectRepository(SigningContractEntity)
    private readonly signingContractRepository: Repository<SigningContractEntity>,
    @InjectRepository(ContractEntity)
    private readonly contractRepository: Repository<ContractEntity>,
    @InjectRepository(PartnersEntity)
    private readonly partnersRepository: Repository<PartnersEntity>,
    @InjectRepository(SignedContractsEntity)
    private readonly signedContractRepository: Repository<SignedContractsEntity>,
    private readonly configService: ConfigService,
    private readonly cos: COS,
    private dataSource: DataSource
  ) {
  }

  //获取未签署的合同列表
  async getPactList(user: UserEntity) {
    //查询学员合同
    const studentList = await this.signingContractRepository.find({
      where: {
        parent_phone: user.mobile
      },
      relations: {
        contract: true
      }
    });
    for (let i = 0; i < studentList.length; i++) {
      studentList[i]["initiator"] = this.configService.get("COMPANY_NAME");
      if (studentList[i].is_agree === 0) {
        //判断过期时间是否小于当前时间戳
        if (studentList[i].expired_at < (new Date()).getTime() / 1000) {
          studentList[i]["status_cn"] = "已过期";
        } else {
          studentList[i]["status_cn"] = "未签署";
        }
      } else if (studentList[i].is_agree === 1) {
        studentList[i]["status_cn"] = "已签署";
      }
    }
    //查询签署了的合伙人合同
    const partnersList = await this.partnersRepository.find({
      where: {
        userId: user.id
      },
      relations: {
        contract: true
      }
    });
    for (let i = 0; i < partnersList.length; i++) {
      partnersList[i]["initiator"] = this.configService.get("COMPANY_NAME");
      partnersList[i]["status_cn"] = "已签署";
    }
    return { studentList, partnersList };
  }

  //获取合同详情
  async getPactDetail(req: PactDetailDto, user: UserEntity) {
    const contract = await this.contractRepository.findOne({
      where: {
        id: req.pactId
      }
    });
    if (!contract) {
      throw new HttpException("合同信息不存在", 400);
    }
    //判断用户是否签署过
    const signedContract = await this.signedContractRepository.findOne({
      where: {
        contractId: req.pactId,
        userId: user.id
      }
    });
    contract["signed_info"] = null;
    switch (contract.type) {
      case 1://学员合同
      {
        //查询学员签署信息
        contract["signed_info"] = await this.signingContractRepository.findOne({
          where: {
            contract_id: contract.id,
            id: req.signId
          }
        });
        if (contract["signed_info"].is_agree === 0) {
          //判断过期时间是否小于当前时间戳
          if (contract["signed_info"].expired_at < (new Date()).getTime() / 1000) {
            contract["signed_info"]["status_cn"] = "已过期";
          } else {
            contract["signed_info"]["status_cn"] = "未签署";
          }
        } else if (contract["signed_info"].is_agree === 1) {
          contract["signed_info"]["status_cn"] = "已签署";
        }
      }
        break;
      default: {
        if (signedContract) {
          contract["signed_info"] = await this.partnersRepository.findOne({
            where: {
              contractId: contract.id,
              userId: user.id
            }
          });
          contract["signed_info"]["initiator"] = this.configService.get("COMPANY_NAME");
          contract["signed_info"]["status_cn"] = "已签署";
          contract["signed_info"]["success_at"] = contract["signed_info"].createdAt;
        }
      }
    }
    return contract;
  }

  async getPactPreviewPic(pactId: number) {
    const contract = await this.contractRepository.findOne({
      where: {
        id: pactId
      }
    });
    if (!contract) {
      throw new HttpException("合同信息不存在", 400);
    }

    if (contract.preview_url) {
      return {
        preview_url: contract.preview_url
      };
    }

    //下载合同
    const localPath = `${assets_path}/temp/down/${contract.id}.docx`;
    if (await this.cos.downloadFile(`${this.configService.get("TENCENT_COS_URL")}/${contract.contract_url}`, localPath) === false) {
      throw new HttpException("文件加载失败", 500);
    }
    const pdfPath = `${assets_path}/temp/pdf/${contract.id}.pdf`;
    const outputPath = `${assets_path}/temp/image/${contract.id}.jpg`;

    await promiseExec(`fc-list`);
    await promiseExec(
      `export HOME=${assets_path} && soffice --headless --invisible --language=zh-CN --convert-to pdf:writer_pdf_Export  ${localPath} --outdir ${assets_path}/temp/pdf`
    );

    await promiseExec(`convert -background white -alpha remove -density 150 -append ${pdfPath} ${outputPath}`);
    //上传预览图到cos
    const uploadPath = `images/${contract.id}_${generateRandomString(10)}.jpg`;
    await this.cos.uploadFile(outputPath, uploadPath);

    //修改合同信息
    await this.contractRepository.update(contract.id, {
      preview_url: uploadPath
    });

    unlinkFile(localPath);
    unlinkFile(outputPath);
    unlinkFile(pdfPath);

    return {
      preview_url: uploadPath
    };
  }

  //合伙人签署
  async signPact(user: UserEntity, signDto: SignPactDto) {
    //获取合伙人签署明细
    const partnersContracts = await this.partnersRepository.findOne({
      where: {
        contractId: signDto.contract_id,
        userId: user.id
      }
    });
    if (partnersContracts) {
      throw new HttpException("合同已签署", 400);
    }
    //获取合同详情
    const contract = await this.contractRepository.findOne({
      where: {
        id: signDto.contract_id
      }
    });
    if (!contract) {
      throw new HttpException("合同信息不存在", 400);
    }

    //下载合同模版
    const localPath = `${assets_path}/temp/doc/${contract.id}.docx`;
    if (!fs.existsSync(localPath)) {
      console.log(`合同模版不存在，下载合同模版..... localPath:${localPath};downloadPath:${this.configService.get("TENCENT_COS_URL")}/${contract.contract_url}`);
      if (await this.cos.downloadFile(
        `${this.configService.get("TENCENT_COS_URL")}/${contract.contract_url}`,
        localPath
      ) === false) {
        throw new HttpException("文件加载失败", 500);
      }
    }

    //下载签名
    const oldSignerPath = signDto.signer;
    const signerLocalPath = `${assets_path}/temp/image/singer_${contract.id}_${user.id}.png`;
    console.log(`下载签名..... oldSignerPath:${this.configService.get("TENCENT_COS_URL")}/${oldSignerPath};signerLocalPath:${signerLocalPath} `);
    if (await this.cos.downloadFile(
      `${this.configService.get("TENCENT_COS_URL")}/${oldSignerPath}`,
      signerLocalPath
    ) === false) {
      throw new HttpException("文件加载失败", 500);
    }
    signDto.signer = signerLocalPath;
    //生成合同编码
    const { year, month, day } = getCurrentDate();
    const contractCode = `WN${currentTime()}${padWithZeros(contract.max_index)}`;

    //本地文件
    const outputPath = `${assets_path}/temp/doc/${contract.id}_${contractCode}.docx`;

    await convertDocx(localPath, outputPath, {
      contractCode,
      date: `${year}年${month}月${day}日`,
      ...signDto,
      startDate: `${year}年${month}月${day}日`,
      endDate: `${(year + 1)}年${month}月${day}日`
    });
    //上传到cos
    const uploadPath = `documents/${contract.id}/${contractCode}.docx`;
    await this.cos.uploadFile(outputPath, uploadPath);

    //增加合同签署
    const newPartnersContracts = new PartnersEntity();
    newPartnersContracts.contractId = contract.id;
    newPartnersContracts.userId = user.id;
    newPartnersContracts.idCard = signDto.id_card;
    newPartnersContracts.contactName = signDto.contact;
    newPartnersContracts.contactNumber = signDto.contact_way;
    newPartnersContracts.contactAddress = signDto.address;
    newPartnersContracts.wechatId = signDto.wechat;
    newPartnersContracts.signer = oldSignerPath;
    newPartnersContracts.documentUrl = uploadPath;
    newPartnersContracts.contactNo = contractCode;
    newPartnersContracts.createdAt = newPartnersContracts.updatedAt = (new Date()).getTime() / 1000;
    await this.dataSource.transaction(async manager => {
      await manager.save(newPartnersContracts);
      //添加签署记录
      const signedContracts = new SignedContractsEntity();
      signedContracts.contractId = contract.id;
      signedContracts.userId = user.id;
      signedContracts.contractType = contract.type;
      await manager.save(signedContracts);
      //增加合同最大序号和回收数量
      await manager.query(`update contract set max_index = max_index + 1,recycling_num = recycling_num + 1 where id = ${contract.id}`);
    });

    unlinkFile(outputPath);

    return newPartnersContracts;
  }

  //学员签署合同
  async signStudentPact(user: UserEntity, signDto: SignStudentPactDto) {
    const signingContracts = await this.signingContractRepository.findOne({
      where: {
        id: signDto.sign_id,
        contract_id: signDto.contract_id,
        parent_phone: user.mobile,
        is_agree: 0
      },
      relations: {
        contract: true
      }
    });
    if (!signingContracts) {
      throw new HttpException("合同信息不存在或已签署", 400);
    }


    ///下载合同模版
    const localPath = `${assets_path}/temp/doc/${signingContracts.contract.id}.docx`;
    if (!fs.existsSync(localPath)) {
      if (await this.cos.downloadFile(
        `${this.configService.get("TENCENT_COS_URL")}/${signingContracts.contract.contract_url}`,
        localPath
      ) === false) {
        throw new HttpException("文件加载失败", 500);
      }
    }

    //合同编码
    const contractCode = `WN${currentTime()}${padWithZeros(signingContracts.contract.max_index)}`;
    //生成合同
    const outputPath = `${assets_path}/temp/doc/${signingContracts.contract.id}_${contractCode}.docx`;
    const { year, month, day } = getCurrentDate();
    await convertDocx(localPath, outputPath, {
      contractCode,
      name: signingContracts.childs_name,
      date: `${year}年${month}月${day}日`
    });
    //上传到cos
    const uploadPath = `documents/${signingContracts.contract.id}/${contractCode}.docx`;
    await this.cos.uploadFile(outputPath, uploadPath);
    //签署
    await this.dataSource.transaction(async manager => {
      //修改签署状态
      signingContracts.is_agree = 1;
      signingContracts.user_id = user.id;
      signingContracts.success_at = (new Date()).getTime() / 1000;
      signingContracts.contract_no = contractCode;
      signingContracts.documentUrl = uploadPath;
      await manager.save(signingContracts);
      //添加签署记录
      const signedContracts = new SignedContractsEntity();
      signedContracts.contractId = signingContracts.contract.id;
      signedContracts.userId = user.id;
      signedContracts.contractType = signingContracts.contract.type;
      await manager.save(signedContracts);
      //增加合同编号
      await manager.query(`update contract set max_index = max_index + 1 where id = ${signingContracts.contract.id}`);
      //判断是否达到了最大签署数量
      if (signingContracts.contract.sending_num === (signingContracts.contract.recycling_num + 1)) {
        await manager.query(`update contract set status = 2 where id = ${signingContracts.contract.id}`);
      }
      //增加回收数量
      await manager.query(`update contract set recycling_num = recycling_num + 1 where id = ${signingContracts.contract.id}`);
    });
    unlinkFile(outputPath);
  }

  //获取用户已签署的合同列表
  async getUserSigningContracts(user: UserEntity) {
    return await this.signedContractRepository.find({
      where: {
        userId: user.id
      },
      relations: {
        contract: true
      }
    });
  }
}
